﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Http;
using Microsoft.Http.Headers;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Linq;
using x.paypal.settings;
using System.Net;
using x.paypal.model;
using x.paypal.service.Settings;

namespace x.paypal.service
{
    public class PayPalAdaptivePaymentService : IPayPalAdaptivePaymentService
    {
        HttpClient _client;
        RequestHeaders _headers;
        public PayPalAdaptivePaymentService()
        {
            InitializeHttpClient();
        }
        #region IPayPalXService Members

        public PaymentResponse RequestPayment(IPayRequest payRequest)
        {
            try
            {
                HttpContent content = HttpContent.Create(payRequest.AsXML.ToString());
                var result = _client.Send(HttpMethod.POST, Operations.PAY, _headers, content);
                result.EnsureStatusIsSuccessful();
                var xml = result.Content.ReadAsXElement();
                var response = GetPaymentResponse(xml);
                return response;
            }
            catch (Exception e)
            {
                throw new PaymentExecption("PAYPAL PAYMENT REQUEST ERROR "+ e.Message);
            }
            
        }
        /// <summary>
        /// This is still not working ..needs to be sorted out 
        /// </summary>
        /// <param name="executepayRequest"></param>
        /// <returns></returns>
        public PaymentResponse ExecutePayment(IExcecutePayRequest executepayRequest)
        {
            try
            {
                HttpContent content = HttpContent.Create(executepayRequest.AsXML.ToString());
                var result = _client.Send(HttpMethod.POST, Operations.EXECUTEPAYMENT, _headers, content);
                result.EnsureStatusIsSuccessful();
                var xml = result.Content.ReadAsXElement();
                var response = GetPaymentResponse(xml);
                return response; 
            }
            catch (Exception)
            {
                
                throw;
            }
           
        }
        public PaymentDetailsResponse GetPaymentDetails(IPaymentDetailsRequest payDetailsRequest)
        {
            try
            {
                HttpContent content = HttpContent.Create(payDetailsRequest.AsXML.ToString());
                var result = _client.Send(HttpMethod.POST, Operations.PAYMENTDETAILS, _headers, content);
                result.EnsureStatusIsSuccessful();
                var xml = result.Content.ReadAsXElement();
                var response = GetPaymentDetailsResponse(xml);
                return response; 
            }
            catch (Exception e)
            {

                throw new PaymentExecption("GET PAYPAL PAYMENT DETAILS ERROR " + e.Message);
            }
            
        }
        #endregion
        #region Private methods
        private static PaymentResponse GetPaymentResponse(XElement xml)
        {
            var response = new PaymentResponse
            {
                ACK = (string)xml.Element("responseEnvelope").Element("ack"),
                CorrelationId = (string)xml.Element("responseEnvelope").Element("correlationId"),
                TimeStamp = (DateTime)xml.Element("responseEnvelope").Element("timestamp"),
                PayKey = (string)xml.Element("payKey"),
                PaymentExecStatus = (string)xml.Element("paymentExecStatus"),
                ErrorList = (from x in xml.Descendants("error")
                             select new Error
                             {
                                 ErrorId = (string)x.Element("errorId"),
                                 Category = (string)x.Element("category"),
                                 Message = (string)x.Element("message"),
                                 Severity = (string)x.Element("severity"),
                             }),
                AsXML = xml
            };
            return response;
        }
        private static PaymentDetailsResponse GetPaymentDetailsResponse(XElement xml)
        {
            var response = new PaymentDetailsResponse
            {
                ACK = (string)xml.Element("responseEnvelope").Element("ack"),
                CorrelationId = (string)xml.Element("responseEnvelope").Element("correlationId"),
                TimeStamp = (DateTime)xml.Element("responseEnvelope").Element("timestamp"),
                PayKey = (string)xml.Element("payKey"),
                PaymentInformationList = (from x in xml.Descendants("paymentInfoList")
                                          select new PaymentInformation
                                          {
                                           Receiver = new Receiver
                                           {
                                               Amount = (string)x.Element("paymentInfo").Element("receiver").Element("amount"),
                                               Email = (string)x.Element("paymentInfo").Element("receiver").Element("email"),
                                               IsPrimary = (bool)x.Element("paymentInfo").Element("receiver").Element("primary"),
                                               InvoiceId = (string)x.Element("paymentInfo").Element("receiver").Element("invoiceId")
                                           }
                                           //PendingRefund = (bool)x.Element("paymentInfo").Element("pendingRefund"),
                                           //RefundedAmount = (decimal)x.Element("paymentInfo").Element("refundedAmount"),
                                           //SenderTransactionId = (string)x.Element("paymentInfo").Element("transactionId"),
                                           //SenderTransactionStatus = (string)x.Element("paymentInfo").Element("transactionStatus")
                                          }),
                AsXML = xml,
                SenderEmail = (string)xml.Element("senderEmail"),
                ErrorList = (from x in xml.Descendants("error")
                             select new Error
                             {
                                 ErrorId = (string)x.Element("errorId"),
                                 Category = (string)x.Element("category"),
                                 Message = (string)x.Element("message"),
                                 Severity = (string)x.Element("severity"),
                             }),
                Status = (string)xml.Element("status")
            };
            return response;
        }
        private void InitializeHttpClient()
        {
            _client = new HttpClient(Configuration.BaseUrl);
            IWebProxy proxy = WebRequest.GetSystemWebProxy();
            proxy.Credentials = CredentialCache.DefaultCredentials;
            _client.TransportSettings.Proxy = proxy;
            _headers = new RequestHeaders();
            _headers.Add(Header.USERID, Security.UserId);
            _headers.Add(Header.PASSWORD, Security.Pwd);
            _headers.Add(Header.SIGNATURE, Security.Signature);
            _headers.Add(Header.APPLICATION_ID, Security.ApplicationId);
            _headers.Add(Header.REQUEST_DATAFORMAT, "XML");
            _headers.Add(Header.RESPONSE_DATAFORMAT, "XML");
        }
        #endregion


       
    }
}